package com.jsmtr.rms.dao.impl;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.jsmtr.rms.entity.SystemLog;
import org.apache.commons.collections4.Transformer;
import org.hibernate.*;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

import com.jsmtr.rms.dao.DaoService;


public class DaoServiceImpl extends HibernateDaoSupport implements DaoService {

    /*
     * 保存日志(单独保存避免日志切面中监控add方法发送死循环)
     * @author cyx
     * @date 2019/4/12 13:42
     * @param log
     * @return void
     */
    @Override
    public void saveLog(SystemLog log) throws Exception {
        Session session = getSessionFactory().openSession();
        Transaction tran = session.beginTransaction();
        //getHibernateTemplate().save(log);
        try {
            session.save(log);
            tran.commit();
        } catch (Exception e) {
            tran.rollback();
            throw e;
        } finally {
            if (session.isOpen()) {
                session.close();
            }
        }


    }

    @Override
    public void add(Object obj) throws Exception {
        getHibernateTemplate().save(obj);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public void addAll(final List list) throws Exception {
        getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                for (Object obj : list) {
                    session.save(obj);
                }
                return null;
            }
        });
    }

    @Override
    public void delete(Object obj) throws Exception {
        getHibernateTemplate().delete(obj);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public void deleteAll(List list) throws Exception {
        getHibernateTemplate().deleteAll(list);
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeHQL(final String hql) throws Exception {
        int result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                return query.executeUpdate();
            }
        });
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeHQL(final String hql, final String param, final Object value) throws Exception {
        int result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                if (value instanceof Collection) {
                    query.setParameterList(param, (Collection) value);
                } else {
                    query.setParameter(param, value);
                }
                return query.executeUpdate();
            }
        });
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeHQL(final String hql, final Map<String, Object> param) throws Exception {
        int result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                for (Entry<String, Object> entry : param.entrySet()) {
                    if (entry.getValue() instanceof Collection) {
                        query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                    } else {
                        query.setParameter(entry.getKey(), entry.getValue());
                    }
                }
                return query.executeUpdate();
            }
        });
        return result;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public List find(String hql) throws Exception {
        return getHibernateTemplate().find(hql);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public List find(final String hql, final String[] param) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                query.setParameterList("idlist", param);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public List findSqlS(final String sql, final String[] param) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createSQLQuery(sql);
                Type[] typelist = new Type[param.length];
                for (int i = 0; i < param.length; i++) {
                    typelist[i] = new StringType();
                }
            //    query.setParameters(param, typelist);
                query.setParameterList("idlist", param);
                return query.list();
            }
        });
        return list;
    }


    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public List findSql(final String sql, final String[] param) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createSQLQuery(sql);
                query.setParameterList("idlist", param);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public List findSql(final String sql) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createSQLQuery(sql);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public List find(final String hql, final List<String> param) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                query.setParameterList("idlist", param);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public List find(final String hql, final String param, final Object value) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                if (value instanceof Collection) {
                    query.setParameterList(param, (Collection) value);
                } else {
                    query.setParameter(param, value);
                }
                return query.list();
            }

        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List find(final String hql, final Map<String, Object> param) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                for (Entry<String, Object> entry : param.entrySet()) {
                    if (entry.getValue() instanceof Collection) {
                        query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                    } else {
                        query.setParameter(entry.getKey(), entry.getValue());
                    }
                }
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Object findFirst(String hql) throws Exception {
        List list = find(hql);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Object findFirst(String hql, String param, Object value) throws Exception {
        List list = find(hql, param, value);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Object findFirst(String hql, Map<String, Object> param) throws Exception {
        List list = find(hql, param);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List findLimitSql(final String sql, final int first, final int max) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                query.setFirstResult(first);
                query.setMaxResults(max);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List findLimitSqlNew(final String sql, final int first, final int max) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                query.setFirstResult(first);
                query.setMaxResults(max);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List findLimit(final String hql, final int first, final int max) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                query.setFirstResult(first);
                query.setMaxResults(max);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List findLimit(final String hql, final String param, final Object value, final int first, final int max) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                if (value instanceof Collection) {
                    query.setParameterList(param, (Collection) value);
                } else {
                    query.setParameter(param, value);
                }
                query.setFirstResult(first);
                query.setMaxResults(max);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List findLimit(final String hql, final Map<String, Object> param, final int first, final int max) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                for (Entry<String, Object> entry : param.entrySet()) {
                    if (entry.getValue() instanceof Collection) {
                        query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                    } else {
                        query.setParameter(entry.getKey(), entry.getValue());
                    }
                }
                query.setFirstResult(first);
                query.setMaxResults(max);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Object findUniqueSql(final String sql) throws Exception {
        Object obj = getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createSQLQuery(sql);
                return query.uniqueResult();
            }
        });

        System.out.println(obj);
        return obj;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Object findUniqueSqlNew(final String sql) throws Exception {
        Object obj = getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session){
                try {
                    Query query = session.createSQLQuery(sql);
                    return query.uniqueResult();
                }catch (Exception e) {
                    return 0;
                }
            }
        });

        System.out.println(obj);
        return obj;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Object findUnique(final String hql) throws Exception {
        Object obj = getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                return query.uniqueResult();
            }
        });
        return obj;
    }


    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Object findUniqueNew(final String hql) throws Exception {
        Object obj = getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) {
                try {
                    Query query = session.createQuery(hql);
                    return query.uniqueResult();
                }catch (Exception e) {
                    return 0;
                }
            }
        });
        return obj;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Object findUnique(final String hql, final String param, final Object value) throws Exception {
        Object obj = getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                if (value instanceof Collection) {
                    query.setParameterList(param, (Collection) value);
                } else {
                    query.setParameter(param, value);
                }
                return query.uniqueResult();
            }
        });
        return obj;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Object findUnique(final String hql, final Map<String, Object> param) throws Exception {
        Object obj = getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                for (Entry<String, Object> entry : param.entrySet()) {
                    if (entry.getValue() instanceof Collection) {
                        query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                    } else {
                        query.setParameter(entry.getKey(), entry.getValue());
                    }
                }
                return query.uniqueResult();
            }
        });
        return obj;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public Object get(Class entityClass, Serializable id) throws Exception {
        return getHibernateTemplate().get(entityClass, id);
    }

    @Override
    public void merge(Object obj) throws Exception {
        getHibernateTemplate().saveOrUpdate(obj);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public void mergeAll(List list) throws Exception {
        getHibernateTemplate().saveOrUpdate(list);
    }

    @Override
    public void update(Object obj) throws Exception {
        getHibernateTemplate().update(obj);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public void updateAll(final List list) throws Exception {
        getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                for (Object obj : list) {
                    session.update(obj);
                }
                return null;
            }
        });
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeSQL(final String sql) throws Exception {
        Integer result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                return query.executeUpdate();
            }
        });
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeSQLs(final List<String> sqls) throws Exception {
        Integer result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                int result = 0;
                for (String sql : sqls) {
                    result += session.createSQLQuery(sql).executeUpdate();
                }
                return result;
            }
        });
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeSQL(final String sql, final String param, final Object value) throws Exception {
        Integer result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                if (value instanceof Collection) {
                    query.setParameterList(param, (Collection) value);
                } else {
                    query.setParameter(param, value);
                }
                return query.executeUpdate();
            }
        });
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public int executeSQL(final String sql, final Map<String, Object> param) throws Exception {
        Integer result = (Integer) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                for (Entry<String, Object> entry : param.entrySet()) {
                    if (entry.getValue() instanceof Collection) {
                        query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                    } else {
                        query.setParameter(entry.getKey(), entry.getValue());
                    }
                }
                return query.executeUpdate();
            }
        });
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List executeSQLQuery(final String sql) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List executeSQLQuery(final String sql, final String param, final Object value) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                if (value instanceof Collection) {
                    query.setParameterList(param, (Collection) value);
                } else {
                    query.setParameter(param, value);
                }
                return query.list();
            }
        });
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public List executeSQLQuery(final String sql, final Map<String, Object> param) throws Exception {
        List list = (List) getHibernateTemplate().execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                SQLQuery query = session.createSQLQuery(sql);
                for (Entry<String, Object> entry : param.entrySet()) {
                    if (entry.getValue() instanceof Collection) {
                        query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                    } else {
                        query.setParameter(entry.getKey(), entry.getValue());
                    }
                }
                return query.list();
            }
        });
        return list;
    }

    @Override
    public List<Map<String, Object>> executeSQLQueryToMap(final String sql, final Map<String, Object> param) throws Exception {
        List<Map<String, Object>> result = getHibernateTemplate()
                .execute(new HibernateCallback<List<Map<String, Object>>>() {
                    @Override
                    public List<Map<String, Object>> doInHibernate(Session session) throws HibernateException {
                        SQLQuery query = session.createSQLQuery(sql);
                        if (param != null && param.size() > 0) {
                            for (Entry<String, Object> entry : param.entrySet()) {
                                if (entry.getValue() instanceof Collection) {
                                    query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                                } else {
                                    query.setParameter(entry.getKey(), entry.getValue());
                                }
                            }
                        }
                        return query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
                    }
                });
        return result;
    }

    @Override
    public List<Map<String, Object>> executeSQLQueryMapPage(String sql, Map<String, Object> param, Integer first, Integer max) throws Exception {
        // Session session =  getHibernateTemplate().getSessionFactory().getCurrentSession();
        SessionFactory sessionFactory = getHibernateTemplate().getSessionFactory();
        Session session = sessionFactory.openSession();
        SQLQuery query = session.createSQLQuery(sql);
        if (param != null && param.size() > 0) {
            for (Entry<String, Object> entry : param.entrySet()) {
                if (entry.getValue() instanceof Collection) {
                    query.setParameterList(entry.getKey(), (Collection) entry.getValue());
                } else {
                    query.setParameter(entry.getKey(), entry.getValue());
                }
            }
        }

        if (first != null) {
            query.setFirstResult(first);
        }
        if (max != null) {
            query.setMaxResults(max);
        }
        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List result = null;
        try {
            result = query.list();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.close();
        }
        return result;
    }
}